
//Kernel Memory Manager
// This code is crude...really haxed up

module kernel.mem.manager;
import kernel.core.util;
import kernel.core.kprintf; // for debug

static uint mem_lower = 0;
static uint mem_upper = 0;
static uint kern_addr = 0;

struct aout_symbol_table {
	uint tabsize;
	uint strsize;
	uint addr;
	uint reserved;
}

struct elf_section_header_table {
	uint num;
	uint size_of;
	uint addr;
	uint shndx;
}

struct multiboot_info {
	uint flags;
	uint mem_lower;
	uint mem_upper;
	uint boot_device;
	uint cmdline;
	uint mods_count;
	uint mods_addr;
	union {
		aout_symbol_table aout_sym;
		elf_section_header_table elf_sec;
	}
	uint mmap_length;
	uint mmap_addr;
}


struct MemoryManager {
static:
public:
	bool init(uint _kernAddr) {
		multiboot_info *multistruct = cast(multiboot_info*)_kernAddr;
		upperLimit = multistruct.mem_upper;
		lowerLimit = multistruct.mem_lower;
		kernAddress = _kernAddr;
		current = cast(void*)_kernAddr;
		return true;
	}

	void *allocate(uint size) {
		kprintf!("{}")("Allocating ");
		kprintf!("{x}")(size);
		kprintfln!("{}")(" bytes\n");
		current = current - size;
		//memcpy(cast(void*)current, cast(void*)0, size);
		return current;
	}

	/**
	  * Copies data from a source piece of memory to a destination piece of memory.
	  * @params:
	  * @dest: A pointer to the piece of memory serving as the copy destination.
	  * @src: A pointer to the piece of memory serving as the copy source.
	  * @count: The number of bytes to copy form src to dest.
	  * @return: A void pointer to the start of the destination data (dest).
	**/
	void *memcpy(void* dest, void* src, size_t count) {
		ubyte *d = cast(ubyte*)dest;
		ubyte *s = cast(ubyte*)src;

		for(size_t i = count; count; count--, d++, s++) {
			*d = *s;
			return dest;
		}
	}

private:
	uint upperLimit;
	uint lowerLimit;
	uint kernAddress;
	void *current;
}

/*
// Tell the memory manager about the environment 
void initMemManager(uint upper, uint lower, uint addr)
{
	mem_lower = lower;
	mem_upper = upper;
	kern_addr = addr;
}

void* malloc(uint size)
{
	return null;
}
*/
